{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 对数组的迭代\n",
    "Numpy包中有一个迭代器对象`numpy.nditer`。它是一个多维迭代器，可以在数组上进行迭代。数组的每个元素可使用Python的标准`Iterator`接口来访问。  \n",
    "下面使用arange()函数创建一个3*4的数组，并使用`nditer`对它进行迭代。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**示例1**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a1_1 = np.arange(0,60,5).reshape(3,4)\n",
    "a1_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 5 10 15 20 25 30 35 40 45 50 55 "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(a1_1):\n",
    "    print(x,end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**示例2**  \n",
    "迭代的顺序匹配数组的**内容布局**，而不考虑特定的排序。  \n",
    "这可以通过迭代上述数组的转置来观察。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a1_2 = np.arange(0,60,5).reshape(3,4)\n",
    "a1_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0, 20, 40],\n",
       "       [ 5, 25, 45],\n",
       "       [10, 30, 50],\n",
       "       [15, 35, 55]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转置a1_2\n",
    "a1_2.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 5 10 15 20 25 30 35 40 45 50 55 "
     ]
    }
   ],
   "source": [
    "# 迭代转置后的a2\n",
    "for x2 in np.nditer(a1_2.T):\n",
    "    print (x2,end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 迭代顺序\n",
    "如果相同元素使用F风格顺序存储，则迭代器选择以更有效的方式对数组进行迭代。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 以C风格顺序排序"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**示例1**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a2_1 = np.arange(0,60,5).reshape(3,4)\n",
    "a2_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0, 20, 40],\n",
       "       [ 5, 25, 45],\n",
       "       [10, 30, 50],\n",
       "       [15, 35, 55]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转置a2_1\n",
    "a2_1.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a2_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以C风格顺序排序\n",
    "c_a2_1 = a2_1.copy(order='C')\n",
    "c_a2_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 5 10 15 20 25 30 35 40 45 50 55 "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(c_a2_1):\n",
    "    print (x,end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 以F风格顺序排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a2_2 = np.arange(0,60,5).reshape(3,4)\n",
    "a2_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看原数组\n",
    "a2_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以F风格顺序排序\n",
    "f_a2_2 = a2_2.copy(order='F')\n",
    "f_a2_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 20 40 5 25 45 10 30 50 15 35 55 "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(f_a2_2):\n",
    "    print(x,end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 强制nditer对象来使用某种顺序\n",
    "可以通过显示提醒，来强制`nditer`对象来使用某种顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a2_3 = np.arange(0,60,5).reshape(3,4)\n",
    "a2_3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 5 10 15 20 25 30 35 40 45 50 55 "
     ]
    }
   ],
   "source": [
    "# 强制nditer对象以C风格顺序排序：\n",
    "for x in np.nditer(a2_3, order='C'):\n",
    "    print(x, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a2_3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 20 40 5 25 45 10 30 50 15 35 55 "
     ]
    }
   ],
   "source": [
    "# 强制nditer对象以F风格顺序排序\n",
    "for x in np.nditer(a2_3, order='F'):\n",
    "    print(x, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a2_3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 修改数组的值\n",
    "`nditer`对象有另一个可选参数`op_flags`。  \n",
    "其默认值为只读，但也可以设置为只写、读+写模式。  \n",
    "这将允许使用此迭代器修改数组元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10],\n",
       "       [15, 20, 25],\n",
       "       [30, 35, 40],\n",
       "       [45, 50, 55]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a3 = np.arange(0,60,5).reshape(4,3)\n",
    "a3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10],\n",
       "       [15, 20, 25],\n",
       "       [30, 35, 40],\n",
       "       [45, 50, 55]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a3[...]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0, 15, 30, 45])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a3[...,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 5, 20, 35, 50])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a3[...,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "index 3 is out of bounds for axis 1 with size 3",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-23-7e2577def333>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma3\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m...\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m: index 3 is out of bounds for axis 1 with size 3"
     ]
    }
   ],
   "source": [
    "a3[...,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,  40,  80],\n",
       "       [120, 160, 200],\n",
       "       [240, 280, 320],\n",
       "       [360, 400, 440]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for x in np.nditer(a3, op_flags=['readwrite']):\n",
    "    x[...]=2*x\n",
    "#     print(2*x,end=' ')\n",
    "# 修改后的数组\n",
    "a3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 外部循环\n",
    "`nditer`类的构造器拥有`flags`参数，它可以接受下列值："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|参数|描述|\n",
    "|:-|:-|\n",
    "|c_index|可以跟踪C顺序的索引\n",
    "|f_index|可以跟踪Fortran顺序的索引\n",
    "|multi_index|每次迭代可以跟踪一种类型的索引\n",
    "|external_loop|遍历输出的值是具有多个值的一维数组，而不是零维数组"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在下面的示例中，迭代器遍历对应于每列的一维数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a4 = np.arange(0,60,5).reshape(3,4)\n",
    "a4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0 20 40]\n",
      "[ 5 25 45]\n",
      "[10 30 50]\n",
      "[15 35 55]\n"
     ]
    }
   ],
   "source": [
    "# 外部循环，按F顺序排序\n",
    "for x in np.nditer(a4, flags=['external_loop'],order='F'):\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0  5 10 15 20 25 30 35 40 45 50 55]\n"
     ]
    }
   ],
   "source": [
    "# 外部循环，按C顺序排序\n",
    "for x in np.nditer(a4, flags=['external_loop'],order='C'):\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 广播迭代\n",
    "如果两个数组是**可广播的**，`nditer`组合对象能够同时迭代他们。  \n",
    "假设数组a5的维度是3X4，数组b5的维度是1X4，则可使用以下类型的迭代器，使数组b5被广播到a5的大小。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a5 = np.arange(0,60,5).reshape(3,4)\n",
    "a5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a5.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b5 = np.array([1,2,3,4],dtype=int)\n",
    "b5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0:1\n",
      "5:2\n",
      "10:3\n",
      "15:4\n",
      "20:1\n",
      "25:2\n",
      "30:3\n",
      "35:4\n",
      "40:1\n",
      "45:2\n",
      "50:3\n",
      "55:4\n"
     ]
    }
   ],
   "source": [
    "for x,y in np.nditer([a5,b5]):\n",
    "    print(\"%d:%d\" %(x,y),end='\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.00:1\n",
      "5.00:2\n",
      "10.00:3\n",
      "15.00:4\n",
      "20.00:1\n",
      "25.00:2\n",
      "30.00:3\n",
      "35.00:4\n",
      "40.00:1\n",
      "45.00:2\n",
      "50.00:3\n",
      "55.00:4\n"
     ]
    }
   ],
   "source": [
    "for x,y in np.nditer([a5,b5]):\n",
    "    print(\"%.2f:%d\" %(x,y),end='\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
